home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-01
/
piano.zip
/
PIANO.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1992-09-06
|
13KB
|
403 lines
// filename PIANO.CPP
// author Robert Upleger
// intent To simulate a piano keyboard.
// To use graphics to display a piano keyboard on the screen.
// To play the proper sound for each corresponding key
// either from the computer keyboard or from disk.
// To "light-up" each note that is played.
//
// project To demonstrate the various features of Turbo C++
// as described in Lafore. This program includes the use
// of inheritence, external files, and virtual functions.
//
// class CSc 311-31 Ahlborn
// assignment Programming assignment #4 - Final Project
// due-date 07-31-92
// reference Robert LaFore (The Waite Group's)
// "Object-Oriented Programming in Turbo C++"
// Waite Group Press, 1992 - Chapter 11 & 15
//
// description The program starts with a display of a piano keyboard.
// A menu of options appears below the piano.
// The user is presented with four options:
//
// OPTION #1
// This option will display the keys on the computer
// keyboard necessary to play the piano.
//
// OPTION #2
// This option will play an old Motown song:
// 'You really got a hold on me.'
//
// OPTION #3
// This option plays the scales, forward then backward.
//
// OPTION #4
// This option terminates the program.
//
// restriction For VGA monitors only.
//
#include <graphics.h> // for initgraph(), etc
#include <stdlib.h> // for exit()
#include <conio.h> // for getch()
#include <dos.h> // for delay(), sound(), etc
#include <fstream.h> // for cout, etc
#include <ctype.h> // for toupper()
enum keystatus { notpushed, pushed } ; // keyboard status
keystatus kstatus = notpushed ; // initialize to notpushed
struct Note // structure for note data stored on disk
{
char letter ; // a letter from the keyboard
float delay ; // the sound delay in milliseconds
};
class key // base class for a key type
{
protected:
int left, top, right, bottom ; // drwaing coordinates
int color ; // key color
float freq; // note frequency
public:
key( int l, int t, int r, int b , float f )
{ left=l; top=t; right=r; bottom=b; freq=f; }
virtual void drawkey() = 0 ; // pure virtual function
virtual void makesound ( float del ) = 0 ;
};
class Lkey : public key // piano key with a left nub
{
public:
Lkey( int l, int t, int r, int b, float f ) :
key( l, t, r, b, f ) {}
void drawkey()
{
// draw key and fill it with pattern & color
int intarr[ 12 ] ;
int* p = intarr ;
*(p +0) = left + 8 ; *(p +1) = top ;
*(p +2) = right ; *(p +3) = top ;
*(p +4) = right ; *(p +5) = bottom ;
*(p +6) = left ; *(p +7) = bottom ;
*(p +8) = left ; *(p +9) = top+64 ;
*(p+10) = left + 8 ; *(p+11) = top+64 ;
color = ( ( kstatus ) ? BLUE : WHITE ) ;
setfillstyle( SOLID_FILL , color ) ;
fillpoly( 6 , p ) ;
setcolor( 0 );
rectangle( left+1, top+1, right-1, bottom-1 );
}
void makesound ( float del )
{
sound( freq ) ; // play note
delay( del ) ; // delay millliseconds
nosound() ; // stop sound
}
};
class Rkey : public key // piano key with a right nub
{
public:
Rkey( int l, int t, int r, int b, float f ) :
key( l, t, r, b, f ) {}
void drawkey()
{
// draw key and fill it with pattern & color
int intarr[ 12 ] ;
int* p = intarr ;
*(p +0) = left ; *(p +1) = top ;
*(p +2) = left + 16 ; *(p +3) = top ;
*(p +4) = left + 16 ; *(p +5) = top+64 ;
*(p +6) = right ; *(p +7) = top+64 ;
*(p +8) = right ; *(p +9) = bottom ;
*(p+10) = left ; *(p+11) = bottom ;
color = ( ( kstatus ) ? BLUE : WHITE ) ;
setfillstyle( SOLID_FILL , color ) ;
fillpoly( 6 , p ) ;
setcolor( 0 ) ;
rectangle( left+1, top+1, right-1, bottom-1 );
}
void makesound ( float del )
{
sound( freq ) ; // play note
delay( del ) ; // delay millliseconds
nosound() ; // stop sound
}
};
class Bkey : public key // the black piano keys
{
public:
Bkey( int l, int t, int r, int b, float f ) :
key( l, t, r, b, f ) {}
void drawkey()
{
// draw key and fill it with pattern & color
int intarr[ 10 ] ;
int* p = intarr ;
*(p +0) = left ; *(p +1) = top ;
*(p +2) = right ; *(p +3) = top ;
*(p +4) = right ; *(p +5) = bottom ;
*(p +6) = left ; *(p +7) = bottom ;
*(p +8) = left ; *(p +9) = top ;
color = ( ( kstatus ) ? RED : BLACK ) ;
setfillstyle( SOLID_FILL, color ) ;
fillpoly( 5, p ) ;
setcolor( getmaxcolor() ) ;
rectangle( left+1, top+1, right-1, bottom-1 ) ;
}
void makesound ( float del )
{
sound( freq ) ; // play note
delay( del ) ; // delay millliseconds
nosound() ; // stop sound
}
} ;
class Ckey : public key // piano keys inbetween the black keys
{
public:
Ckey( int l, int t, int r, int b, float f ) :
key( l, t, r, b, f ) {}
void drawkey()
{
// draw key and fill it with pattern & color
int intarr[ 16 ] ;
int* p = intarr ;
*(p +0) = left + 8 ; *(p +1) = top ;
*(p +2) = left + 16 ; *(p +3) = top ;
*(p +4) = left + 16 ; *(p +5) = top+64 ;
*(p +6) = right ; *(p +7) = top+64 ;
*(p +8) = right ; *(p +9) = bottom ;
*(p+10) = left ; *(p+11) = bottom ;
*(p+12) = left ; *(p+13) = top+64 ;
*(p+14) = left + 8 ; *(p+15) = top+64 ;
color = ( ( kstatus ) ? BLUE : WHITE ) ;
setfillstyle( SOLID_FILL , color ) ;
fillpoly( 8 , p ) ;
setcolor( 0 ) ;
rectangle( left+1, top+1, right-1, bottom-1 );
}
void makesound ( float del )
{
sound( freq ) ; // play note
delay( del ) ; // delay millliseconds
nosound() ; // stop sound
}
};
int main()
{
int gdriver = DETECT ; // auto detection
int gmode, errorcode ;
initgraph( &gdriver, &gmode, "" ); // initialize graphics
errorcode = graphresult(); // get error code
if ( errorcode != 0 ) // an error occurred
{
cout << "Graphics error: " << grapherrormsg( errorcode ) ;
getch() ;
exit(1) ; // exit program
}
// initialize piano keys note keyboard
// -------------------------------- --------- --------
Rkey A( 40, 40, 64, 160, 261.63 ) ; // c natural char a
Bkey W( 56, 40, 72, 104, 277.48 ) ; // c sharp char w
Ckey S( 64, 40, 88, 160, 293.66 ) ; // d natural char s
Bkey E( 80, 40, 96, 104, 311.65 ) ; // e flat char e
Lkey D( 88, 40, 112, 160, 329.63 ) ; // e natural char d
Rkey F( 112, 40, 136, 160, 349.23 ) ; // f natural char f
Bkey T( 128, 40, 144, 104, 370.62 ) ; // f sharp char t
Ckey G( 136, 40, 160, 160, 392.00 ) ; // g natural char g
Bkey Y( 152, 40, 168, 104, 416.00 ) ; // g sharp char y
Ckey H( 160, 40, 184, 160, 440.00 ) ; // a natural char h
Bkey U( 176, 40, 192, 104, 466.94 ) ; // a sharp char u
Lkey J( 184, 40, 208, 160, 493.88 ) ; // b natural char j
Rkey K( 208, 40, 232, 160, 523.25 ) ; // c natural char k
Bkey O( 224, 40, 240, 104, 555.28 ) ; // c sharp char o
Ckey L( 232, 40, 256, 160, 587.32 ) ; // d natural char l
// set-up pointers to all the keys
Lkey* Lptr ; // pointer to a left key
Bkey* Bptr ; // pointer to a black key
Rkey* Rptr ; // pointer to a right key
Ckey* Cptr ; // pointer to a center key
// initialize pointers to corresponding note addresses
// and put pointers into array 'keyptr'
key* keyptr[ 15 ] = { Rptr = &A , Bptr = &W , Cptr = &S ,
Bptr = &E , Lptr = &D , Rptr = &F ,
Bptr = &T , Cptr = &G , Bptr = &Y ,
Cptr = &H , Bptr = &U , Lptr = &J ,
Rptr = &K , Bptr = &O , Cptr = &L } ;
// draw piano keyboard with virtual function 'drawkey()'
for ( int j=0 ; j<15 ; j++ )
keyptr[ j ] -> drawkey() ;
// initialize variables and function prototypes
Note note ; // note structure variable
fstream file ; // file from a disk
char ch ; // input character
int mainmenu() ; // prototype
int noteptr( char ) ; // prototype
void cleartext() ; // prototype
void showkeyboard() ; // prototype
void invalidoption() ; // prototype
char option ; // input option
option = toupper(mainmenu()); // initialize option from menu
do // the option that the user entered
{
cleartext() ; // clear the option menu
switch( option ) // decide what option to do
{
case 'A': { // do the piano keyboard
showkeyboard() ; // show keyboard menu
do // keep getting a note
{
ch = getch() ;
// assign the key an array index
int i = noteptr( ch ) ;
// if valid play the piano note
if ( i != 99 )
{
// change keypushed status
kstatus = pushed ;
// draw pushed key
keyptr[ i ] -> drawkey() ;
// play the sound
keyptr[ i ] -> makesound(200);
// change keypushed ststus
kstatus = notpushed ;
// draw unpushed key
keyptr[ i ] -> drawkey() ;
}
}
while ( ch != 'x' );
break;
}
case 'B': // play one of two songs
case 'C': {
if ( option == 'B' )
// play Motown
file.open( "SONG.DAT" , ios::in ) ;
// else play the scales
else file.open( "SONG1.DAT" , ios::in );
file.seekg(0) ; // goto begin of file
// read the note structure
file.read( (char*)¬e, sizeof( note ) ) ;
while ( !file.eof() )
{ // play the note
float del = note.delay;
ch = note.letter ;
kstatus = pushed ;
int i = noteptr( ch ) ;
keyptr[ i ] -> drawkey() ;
keyptr[ i ] -> makesound(del) ;
kstatus = notpushed ;
keyptr[ i ] -> drawkey() ;
file.read( (char*)¬e, sizeof( note ) ) ;
}
file.close() ; // close the file
break;
}
default: {
invalidoption(); // invalid option
}
}
cleartext() ;
option = mainmenu() ; // get another option
option = toupper( option ) ;
}
while ( option != 'D' ) ; // 'D' means quit
cleardevice() ; // clear the graphics screen
closegraph(); // shuts down the graphics system
return(0) ; // return zero, program ran ok
}
char mainmenu() // the main menu for user option
{
char choice ;
gotoxy( 1, 1 ) ; cout << " P I A N O S I M U L A T I O N " ;
gotoxy( 1, 2 ) ; cout << " ---------------------------------------- " ;
gotoxy( 5, 13 ) ; cout << " A. This option allows you to play " ;
gotoxy( 5, 14 ) ; cout << " the keyboard like a piano. " ;
gotoxy( 5, 16 ) ; cout << " B. This option will play a song: " ;
gotoxy( 5, 17 ) ; cout << " \'You really got a hold on me.\'" ;
gotoxy( 5, 19 ) ; cout << " C. This option will play a scale . " ;
gotoxy( 5, 21 ) ; cout << " D. Quit program " ;
gotoxy( 5, 24 ) ; cout << " ENTER OPTION: " ;
gotoxy( 30, 24) ; choice = getch() ;
return ( choice ) ;
}
void cleartext() // clears the mainmenu() text
{
for ( int j=13; j<30; j++ )
{
gotoxy( 1, j ) ;
cout << " \
";
}
}
void showkeyboard() // displays message on how to play the keyboard
{
gotoxy( 5, 13 ) ; cout << " W E T Y U O " ;
gotoxy( 5, 14 ) ; cout << " A S D F G H J K L " ;
gotoxy( 35, 13 ) ; cout << " <- THESE ARE THE BLACK KEYS " ;
gotoxy( 35, 14 ) ; cout << " <- THESE ARE THE WHITE KEYS " ;
gotoxy( 5, 18 ) ; cout << " PLAY THESE LETTERS ON THE KEYBOARD " ;
gotoxy( 5, 20 ) ; cout << " TYPE 'x' TO EXIT. " ;
}
int noteptr( char c ) // returns an index to a pointer value
{
if ( c == 'a' ) return( 0 );
if ( c == 'w' ) return( 1 );
if ( c == 's' ) return( 2 );
if ( c == 'e' ) return( 3 );
if ( c == 'd' ) return( 4 );
if ( c == 'f' ) return( 5 );
if ( c == 't' ) return( 6 );
if ( c == 'g' ) return( 7 );
if ( c == 'y' ) return( 8 );
if ( c == 'h' ) return( 9 );
if ( c == 'u' ) return( 10 );
if ( c == 'j' ) return( 11 );
if ( c == 'k' ) return( 12 );
if ( c == 'o' ) return( 13 );
if ( c == 'l' ) return( 14 );
else return ( 99 ) ;
}
void invalidoption() // invalid option selected - displays message
{
gotoxy( 5, 22 ); cout << "\a\aInvalid option - try again. " ;
gotoxy( 5, 24 ) ; cout << "Hit any key... " ;
getch() ;
gotoxy( 5 , 22 ) ; cout << " ";
gotoxy( 5 , 24 ) ; cout << " ";
}